﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using FinanSoft.Utilities;
using FinanSoft.BusinessLayer;

namespace FinanSoft.Entities
{
    public class AccountingEntry
    {
        #region Fields
        List<AccountingEntryDetail> _details;
        
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor de la clase. Recibe parametros para todos los atributos del asiento
        /// </summary>
        public AccountingEntry(int id, Season season, DocType type, User user, DateTime accDate, DateTime docDate, string ref1, string ref2, string ref3, List<AccountingEntryDetail> entries)
        {
            this.Id = id;
            this.Season = season;
            this.Type = type;
            this.User = user;
            this.AccountingDate = accDate;
            this.DocDate = docDate;
            this.Ref1 = ref1;
            this.Ref2 = ref2;
            this.Ref3 = ref3;
            this.EntryDetails = entries;
        }

        /// <summary>
        /// Constructor por defecto de la clase
        /// </summary>
        public AccountingEntry()
        {
            _details = new List<AccountingEntryDetail>();
        }
        #endregion

        #region Properties
        /// <summary>
        /// Numero que identifica de manera unica el asiento
        /// </summary>
        public int Id
        {
            get;
            set;
        }

        /// <summary>
        /// Tipo de documento del asiento
        /// </summary>
        public DocType Type
        {
            get;
            set;
        }

        /// <summary>
        /// Fecha del documento
        /// </summary>
        public DateTime DocDate
        {
            get;
            set;
        }

        public DateTime AccountingDate
        {
            get;
            set;
        }

        /// <summary>
        /// Temporada en la que se registra el asiento
        /// </summary>
        public Season Season
        {
            get;
            set;
        }

        /// <summary>
        /// Usuario que registra el asiento
        /// </summary>
        public User User
        {
            get;
            set;
        }

        /// <summary>
        /// Referencias 1 del asiento
        /// </summary>
        public string Ref1
        {
            get;
            set;
        }

        /// <summary>
        /// Referencia 2 del asiento
        /// </summary>
        public string Ref2
        {
            get;
            set;
        }

        /// <summary>
        /// Referencia 3 del asiento
        /// </summary>
        public string Ref3
        {
            get;
            set;
        }

        /// <summary>
        /// Lista con las cuentas afectadas, el tipo de crecimiento y el monto. Se le llama detalles del asiento.
        /// </summary>
        public List<AccountingEntryDetail> EntryDetails
        {
            get
            {return this._details;}

            set
            { 
                this._details = value;
                IdentifyDetails();
            }
        }
        #endregion

        #region Methods

        /// <summary>
        /// Asigna un identificador a cada uno de los objetos detalle del asiento
        /// </summary>
        private void IdentifyDetails()
        {
            int index;

            index = 1;

            foreach (AccountingEntryDetail detail in _details)
            {
                detail.Id = index;
                index++;
            }
        }

        /// <summary>
        /// Convierte la lista de detalles del asiento a formato XML
        /// </summary>
        public XmlDocument DetailsToXML()
        {
            XmlDocument newDoc;

            newDoc = new XmlDocument();
            string xmlData = Constants.ROOT_NODE_BEGINNING + Constants.ROOT_NODE_ENDING;

            newDoc.Load(new StringReader(xmlData));


            foreach (AccountingEntryDetail detail in this.EntryDetails)
            {
                newDoc = detail.ToXML(newDoc);
            }

            return newDoc;
        }

        /// <summary>
        /// Construye un objeto detalle, que consisten en un par cuenta - monto y el tipo de crecimiento y que documentan los movimientos del asiento.
        /// Inserta este detalle en la lista de detalles del asiento
        /// </summary>
        /// <param name="entry">Asiento al que se agregara el nuevo detalle</param>
        /// <param name="accId"> Numero de identificacion de la cuenta referenciada en el asiento</param>
        /// <param name="sysAmmount"> Cantidad de dinero en moneda del sistema por la que se modifica la cuenta</param>        
        /// <param name="locAmmount">Cantidad de dinero en moneda local por la que se modifica la cuenta</param>
        /// <param name="type"> Tipo de crecimiento de la cuenta para este movimiento</param>
        public void AddDetail(int accId, double sysAmmount, double locAmmount, Utilities.Constants.AccountingEntryType type)
        {
            AccountingEntryDetail newDetail;
            Account entryAccount;
            int index;

            index = EntryDetails.Count;
            entryAccount = CatalogManager.GetInstance().GetAccount(accId);
            newDetail = new AccountingEntryDetail(index, entryAccount, type, sysAmmount, locAmmount);
            this.EntryDetails.Add(newDetail);
        }

        #endregion
    }
}
